﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FunctionGraph
{
    class IntervalDiv
    {
        public static Interval div_non_zero(Interval x, Interval y)
        {
            var xl = x.Val0;
            var xu = x.Val1;
            var yl = y.Val0;
            var yu = y.Val1;
            if (xu < 0)
                if (yu < 0)
                    return new Interval(Round.DivDown(xu, yl), Round.DivUp(xl, yu));
                else
                    return new Interval(Round.DivDown(xl, yl), Round.DivUp(xu, yu));
            else if (xl < 0)
                if (yu < 0)
                    return new Interval(Round.DivDown(xu, yu), Round.DivUp(xl, yu));
                else
                    return new Interval(Round.DivDown(xl, yl), Round.DivUp(xu, yl));
            else
                if (yu < 0)
                    return new Interval(Round.DivDown(xu, yu), Round.DivUp(xl, yl));
                else
                    return new Interval(Round.DivDown(xl, yu), Round.DivUp(xu, yl));
        }

        public static Interval div_non_zero(double x, Interval y)
        {
            var yl = y.Val0;
            var yu = y.Val1;
            if (x < 0)
                return new Interval(Round.DivDown(x, yl), Round.DivUp(x, yu));
            else
                return new Interval(Round.DivDown(x, yu), Round.DivUp(x, yl));
        }

        public static Interval div_positive(Interval x, double yu)
        {
            var xl = x.Val0;
            var xu = x.Val1;
            if (xl == 0 && xu == 0)
                return x;
            if (xu < 0)
                return new Interval(double.NegativeInfinity, Round.DivUp(xu, yu));
            else if (xl < 0)
                return new Interval(double.NegativeInfinity, double.PositiveInfinity);
            else
                return new Interval(Round.DivDown(xl, yu), double.PositiveInfinity);
        }

        public static Interval div_positive(double x, double yu)
        {
            if (x == 0)
                return new Interval(0, 0);
            if (x < 0)
                return new Interval(double.NegativeInfinity, Round.DivUp(x, yu));
            else
                return new Interval(Round.DivDown(x, yu), double.PositiveInfinity);
        }


        public static Interval div_negative(Interval x, double yl)
        {
            var xl = x.Val0;
            var xu = x.Val1;
            if (xl == 0 && xu == 0)
                return x;

            if (xu < 0)
                return new Interval(Round.DivDown(xu, yl), double.PositiveInfinity);
            else if (xl < 0)
                return new Interval(double.NegativeInfinity, double.PositiveInfinity);
            else
                return new Interval(double.NegativeInfinity, Round.DivUp(xl, yl));
        }


        public static Interval div_negative(double x, double yl)
        {
            if (x == 0)
                return new Interval(0, 0);

            if (x < 0)
                return new Interval(Round.DivDown(x, yl), double.PositiveInfinity);
            else
                return new Interval(double.NegativeInfinity, Round.DivUp(x, yl));
        }


        public static Interval div_zero(Interval x)
        {
            if (x.Val0 == 0 && x.Val1 == 0)
                return x;
            else return new Interval(double.NegativeInfinity, double.PositiveInfinity) { Def1 = false, Def0 = false, Cont0 = false, Cont1 = false };
        }


        public static Interval div_zero(double x)
        {
            if (x == 0)
                return new Interval(0, 0);
            else return new Interval(double.NegativeInfinity, double.PositiveInfinity) { Def1 = false, Def0 = false, Cont0 = false, Cont1 = false };
        }


        public static Interval div_zero_part1(Interval x, Interval y, ref bool b)
        {
            if (x.Val0 == 0 && x.Val1 == 0)
            {
                b = false;
                return x;
            }

            var xl = x.Val0;
            var xu = x.Val1;
            var yl = y.Val0;
            var yu = y.Val1;

            if (xu < 0)
            { b = true; return new Interval(double.NegativeInfinity, Round.DivUp(xu, yu)); }
            else if (xl < 0)
            { b = false; return new Interval(double.NegativeInfinity, double.PositiveInfinity); }
            else
            { b = true; return new Interval(double.NegativeInfinity, Round.DivUp(xl, yl)); }
        }


        public static Interval div_zero_part2(Interval x, Interval y)
        {
            if (x.Val1 < 0)
                return new Interval(Round.DivDown(x.Val1, y.Val0), double.PositiveInfinity);
            else
                return new Interval(Round.DivDown(x.Val0, y.Val1), double.PositiveInfinity);
        }

    }
}
